"""
    六子棋
    Author: Arisu
    REALISE_DATE:
    简介:
    PyPixel 0.2.5REALISE DEMO
    通过在socket连接的局域网内进行六子棋对战
"""


import pygame

from PyPixelCore.PyPixelController import PyPixelController
from PyPixelCore.Setting import *
from PyPixelCore.block.Block import Block
from PyPixelCore.block.DynamicImageBlock import DynamicImageBlock
from PyPixelCore.block.SelectButton import SelectButton
from PyPixelCore.block.SuperMultiLineTextBlock import SuperMultiLineTextBlock
from PyPixelCore.block.TextBlock import TextBlock
from PyPixelCore.block.TextButton import TextButton
from PyPixelCore.group.BaseGroup import BaseGroup
from PyPixelCore.panel.EditText import EditText
from PyPixelCore.panel.Panel import Panel
from PyPixelCore.panel.PanelList import PanelList
from PyPixelCore.timer.CycleTimer import CycleTimer
from PyPixelCore.timer.OnlyTimer import OnlyTimer
from PyPixelCore.util.ip import *
from PyPixelCore.util.socket.SocketLink import *
from PyPixelCore.util.timer import get_current_time

# 初始化PyPixel引擎
ppc = PyPixelController()

# 一些变量
socket_link_port = 32798  # 要求一个没有被占用的端口
aim_display = "connect5"  # 目标组
now_display = "connect5"  # 当前组
is_online = False  # 在线连接状态
job = None  # True:服务端 False:客户端
# game_state = "no_game"  # 显示当前的游戏进行状态

# 基础组的块
menu_list = PanelList(120,330,10,50)
button_test = TextButton("切换测试组")
text_show_1 = SuperMultiLineTextBlock(text_content="这里是基础组,现在展示的是基础组",limit_h=50,limit_w=200, point_y=200, point_x=200)

clicked_inform = DynamicImageBlock(width=350, height=350, point_y=111, point_x=111, layer=2, is_alpha=False)
clicked_inform.add_image_list_from_file("./recourse/clicked", "clicked",limit=True)
clicked_inform.set_video_state("clicked")
clicked_inform.set_animation_interval(5)
clicked_inform.is_show = False
def monitor_clicked_inform(self):
    if clicked_inform.now_frame_index == clicked_inform.max_frame_index:
        clicked_inform.is_show = False
        clicked_inform.delete_frame_animation()
def clicked_inform_click_animation(pos):
    clicked_inform.is_show = True
    clicked_inform.rect.center = pos
    clicked_inform.now_frame_index = 0
    clicked_inform.set_frame_animation(monitor_clicked_inform)

game_starter_interface = Panel(width=458,height=332,point_x=140,point_y=50,border_width=2, layer=1,bk_color=Color_type.RICE_YELLOW)  # 覆盖在游戏界面的用于选择游戏行为的界面
only_game_button = TextButton("人机棋缘", width=90, height=300, point_y=16, point_x=20)
only_game_button.set_color_no_None(bk_color=Color_type.VERY_LIGHT_GREEN,border_color=Color_type.GREEN,press_color=Color_type.GREEN,hover_color=Color_type.LIGHT_GREEN)
invite_game_button = TextButton("云弈江湖", width=90, height=300, point_y=16, point_x=130)
invite_game_button.set_color_no_None(bk_color=Color_type.VERY_LIGHT_GREEN,border_color=Color_type.GREEN,press_color=Color_type.GREEN,hover_color=Color_type.LIGHT_GREEN)
ending_game_button = TextButton("残章沙盒", width=90, height=300, point_y=16, point_x=240)
ending_game_button.set_color_no_None(bk_color=Color_type.VERY_LIGHT_GREEN,border_color=Color_type.GREEN,press_color=Color_type.GREEN,hover_color=Color_type.LIGHT_GREEN)
review_game_button = TextButton("弈韵回澜", width=90, height=300, point_y=16, point_x=350)
review_game_button.set_color_no_None(bk_color=Color_type.VERY_LIGHT_GREEN,border_color=Color_type.GREEN,press_color=Color_type.GREEN,hover_color=Color_type.LIGHT_GREEN)
game_starter_interface.add_sprites(only_game_button,invite_game_button, ending_game_button, review_game_button)


def game_starter_interface_focus_do(self: Panel, pos):
    # 游戏模式选择界面
    print(f"inner_game_pos: {pos[0] - self.rect.x}, {pos[1] - self.rect.y}")
    clicked_inform_click_animation(pos)

    if not self.is_focus:
        self.is_focus = True
    pass
game_starter_interface.focus_animation_do = game_starter_interface_focus_do

def big_test(self: TextButton):
    self.rect.x-=10
    self.is_dirty = True
only_game_button.set_click_down_func(big_test)

def click_and_swap_screem(self: TextButton):
    # 改变场景的动画与按钮事件
    global aim_display
    if self.text_content == "切换测试组":
        if now_display == "test": return
        aim_display = "test"
    elif self.text_content == "切换基础组":
        if now_display == "base": return
        aim_display = "base"
    elif self.text_content == "切换聊天组":
        if now_display == "talk": return
        aim_display = "talk"
    elif self.text_content == "切换六子棋":
        if now_display == "connect6": return
        aim_display = "connect6"
    elif self.text_content == "切换五子棋":
        if now_display == "connect5": return
        aim_display = "connect5"
    # 动画播放的准备
    ppc.ban_click = True
    screen_refresh_left.rect.x = -window_width
    screen_refresh_left.state_to_move = True
    screen_refresh_left.set_frame_animation(swap_screen)
    screen_refresh_right.rect.x = window_width
    group_load.show()

block_inform = Block(25, 25, (255, 255, 255, 0), is_alpha=True, layer=2)
block_inform.load_image("./recourse/warning.png", True)
block_inform.is_show = False
def warning_animation(point_x,point_y, vibrate_arr):
    block_inform.rect.x = point_x
    block_inform.rect.y = point_y
    block_inform.vibrate_arr = vibrate_arr
    block_inform.vibrate_index = 0
    block_inform.is_show = True
    block_inform.alpha_value = 255
    block_inform.image.set_alpha(255)
    block_inform.delete_timer_animation(warning_animation_1)
    block_inform.delete_timer_animation(warning_animation_change_animation)
    block_inform.delete_frame_animation()
    block_inform.set_timer_animation(CycleTimer(2), warning_animation_1)
    block_inform.set_timer_animation(OnlyTimer(fps_limit/2), warning_animation_change_animation)
def warning_animation_1(self: Block):  # 震动的动画
    block_inform.rect.x += block_inform.vibrate_arr[block_inform.vibrate_index][0]
    block_inform.rect.y += block_inform.vibrate_arr[block_inform.vibrate_index][1]
    block_inform.vibrate_index = (block_inform.vibrate_index + 1) % len(block_inform.vibrate_arr)
def warning_animation_2(self: Block):  # 逐渐消失的动画
    block_inform.alpha_value -= 30
    if block_inform.alpha_value < 0:
        block_inform.is_show = False
        block_inform.delete_frame_animation()
    block_inform.image.set_alpha(block_inform.alpha_value)
def warning_animation_change_animation(self: Block):
    self.delete_timer_animation(warning_animation_1)
    self.set_frame_animation(warning_animation_2)

# 测试组的块
button_base = TextButton("切换基础组")
text_show_2 = SuperMultiLineTextBlock(text_content="这里是测试组,现在展示的是测试组",limit_h=50,limit_w=200,point_y=200,point_x=300)


# 游戏connect5(五子棋)组的块
button_connect5 = TextButton("切换五子棋")
net_game_message = EditText(width=105, height=150, point_x=602, point_y=50, border_width=2, font_size=12, edit_inner_width=1,game_controller=ppc)
net_game_message.is_edit_able = False
net_game_message.add_text("未连接...\n")
button_connect5_help = TextButton("帮助", point_x=7,point_y=10)
button_connect5_fail = TextButton("认输", point_x=57,point_y=10)
connect5_tool_interface = Panel(width=105, height=178, point_x=602, point_y=204, border_width=2)
connect5_interface = Panel(width=458,height=332,point_x=140,point_y=50,border_width=2)

connect5_interface.add_sprites()


def connect5_main_job(self:Panel,pos):
    # 游戏界面的点击事件(记录坐标方便移动, 点击生成操作菜单)
    print(f"connect5_main_job_inner_game_pos: {pos[0] - self.rect.x}, {pos[1] - self.rect.y}")
    if not self.is_focus:
        self.is_focus = True
connect5_interface.focus_animation_do = connect5_main_job
connect5_tool_interface.add_sprites(button_connect5_help, button_connect5_fail)


# 游戏connect6(六子棋)组的块
button_connect6 = TextButton("切换六子棋")

connect6_tool_inform = Panel(width=105,height=178,point_x=602,point_y=204,border_width=2)
connect6_interface = Panel(width=458,height=332,point_x=140,point_y=50,border_width=2)
def connect6_main_job(self:connect6_interface,pos):
    # 游戏界面的点击事件(记录坐标方便移动, 点击生成操作菜单)
    pass
connect6_interface.focus_animation_do = connect6_main_job

# 聊天室组的块
button_talk = TextButton("切换聊天组")
login_state_text_block = TextBlock("离线", point_x=150,point_y=11, border_width=0)
login_state_text_block.set_font_color(Color_type.RED)
select_job = SelectButton("我是客户端", point_x=210,point_y=10)
ip_text_block = TextBlock("目标ip: ",point_x=360, point_y=12, border_width=0)
input_ip = EditText(width=170,height=22,point_x=434,point_y=10,border_width=1,font_size=basic_font_size,edit_inner_width=0,game_controller=ppc)
input_ip.is_edit_able = True
button_net_link = TextButton("连<->接", point_y=9, point_x=620)
button_net_link.message_dict = {"message": []}
button_net_link.socket = None
message_show = EditText(width=550,height=276,point_x=140,point_y=50,border_width=3,font_size=17,edit_inner_width=4,game_controller=ppc)
message_show.add_text(f"->{get_current_time()}: 未连接\n")
message_show.is_edit_able = False
message_input = EditText(width=500,height=50,point_x=140,point_y=330,border_width=3, font_size=16,edit_inner_width=0,game_controller=ppc)
message_input.set_text_content("-->")
send_button = TextButton("发送", point_y=346,point_x=650,border_width=3)
def input_enter(self: EditText):
    self.add_text("\n")

def send_message(self: TextButton):  # 发送消息
    # 发送信息给对方
    if not is_online:
        warning_animation(111, 8, [(2, 0), (-2, 0), (0, 2), (0, -2)])  # 播放警告动画
        return
    if (text := message_input.get_text()[3:]) == "":
        return
    if not job:  # 客户端发送
        if not button_net_link.socket is None:
            message = PyPixelMessage(message_type.message_talk,text,"客户端","服务端")
            send_message_to_server(button_net_link.socket, message, button_net_link.message_dict)
    else:  # 服务端发送
        message = PyPixelMessage(message_type.message_talk, text, "服务端", "客户端")
        send_message_to_client(button_net_link.message_dict, message)
    message_input.set_text_content("-->")

def start_socket_connection(self: TextButton):  # 创建一个线程执行连接或者监听产生socket连接
    global is_online
    if self.is_clicked and is_online:
        # 执行断开操作
        is_online = False
        close_server_socket(self.message_dict) if job else close_client_socket(self.message_dict)
        self.set_text_content("创<->建" if job else "连<->接")
        login_state_text_block.set_text_display("离线", color=Color_type.RED)
        return
    # 连接创建的时候同时清空信息字典
    self.message_dict = {"stop": False}
    if job:  # 角色是服务端
        is_online = True
        message_show.add_text(f"->创建主服务器\n")
        create_server_socket(input_ip.get_text(),socket_link_port,self.message_dict, message_show)
        self.set_text_content("断x开")
        login_state_text_block.set_text_display("主机", color=Color_type.BRIGHT_BLUE)
    else:  # 角色是客户端
        self.socket = create_client_socket(input_ip.get_text(),socket_link_port,"客户端",self.message_dict, message_show)
        if self.socket:
            is_online = True
            message_show.add_text(f"->连接成功\n")
            self.set_text_content("断x开")
            login_state_text_block.set_text_display("在线", color=Color_type.GREEN)
        else:
            message_show.add_text(f"->连接失败\n")
    self.is_clicked = True
def chose_socket_connection(self: SelectButton):
    global job
    if is_online:
        self.is_clicked = not self.is_clicked
        return
    if self.is_clicked:
        job = True
        self.set_text_content("我是服务端")
        ip_text_block.set_text_content("我的ip:")
        button_net_link.set_text_content("创<->建")
        input_ip.is_edit_able = False
        input_ip.set_text_content(get_local_ip())
    else:
        job = False
        self.set_text_content("我是客户端")
        ip_text_block.set_text_content("目标ip:")
        button_net_link.set_text_content("连<->接")
        input_ip.is_edit_able = True

# 加载组的块
screen_refresh_left = Block(width=window_width, height=window_height, bk_color=Color_type.LIGHT_GREY, point_x=-window_width, layer=2)
screen_refresh_left.state_to_move = False
screen_refresh_right = Panel(width=window_width, height=window_height, bk_color=Color_type.LIGHT_GREY, point_x=window_width, point_y=0, layer=2, border_width=0)
refresh_text = TextBlock("加载中,请稍后..", is_alpha=True, point_y=window_height-50, point_x=-230, border_width=0, layer=2)
refresh_text.set_bk_color(None)
refresh_index = DynamicImageBlock(width=50, height=50, point_y=window_height-65, point_x=-60, layer=2)
refresh_index.add_image_list_from_file("./recourse/load", "load")
refresh_index.set_animation_interval(FPS_type.HIGH_PIXEL)
screen_refresh_right.add_sprites(refresh_index, refresh_text)
def cycle_load(self: TextBlock):
    if not hasattr(self, "index_point"): self.index_point = 2
    if self.index_point < 3:
        self.index_point += 1
        self.set_text_content(self.text_content + ".")
    else:
        self.set_text_content(self.text_content[:-3])
        self.index_point = 0
def swap_screen(self: Block):
    if screen_refresh_left.state_to_move:
        screen_refresh_left.rect.x += 4
        screen_refresh_right.rect.x -= 4
        screen_refresh_right.is_dirty = True
        # 测试
        refresh_text.rect.x += 4
        refresh_index.rect.x += 4
    else:
        screen_refresh_left.rect.x -= 3
        screen_refresh_right.rect.x += 3
        screen_refresh_right.is_dirty = True
        # 测试
        refresh_text.rect.x -= 3
        refresh_index.rect.x -= 3
    if self.rect.x + self.rect.width >= window_height + 60:
        screen_refresh_left.state_to_move = False
        print('切换场景')
        fix_show()
    if self.rect.x < -window_width:
        refresh_index.rect.x = -60
        refresh_text.rect.x = -230
        group_load.hide()
        self.delete_frame_animation()
        ppc.ban_click = False
# panel加载
menu_list.add_sprites(button_test, button_talk, button_base, button_connect6, button_connect5)

# 各种状态的组
group_static = BaseGroup(menu_list, clicked_inform)
group_base = BaseGroup( text_show_1, hide=True)  # 基础的组
group_test = BaseGroup( text_show_2, hide=True)  # 测试用的组
group_connect6 = BaseGroup(connect6_tool_inform, login_state_text_block, net_game_message, connect6_interface, game_starter_interface, hide=True)  # 六子棋游戏组
group_connect5 = BaseGroup(connect5_tool_interface, login_state_text_block, net_game_message, connect5_interface, game_starter_interface, hide=True)  # 五子棋游戏组
group_talk = BaseGroup(select_job, login_state_text_block, ip_text_block, input_ip, button_net_link, message_show, message_input, send_button, hide=True)  # 聊天室的组
group_load = BaseGroup(screen_refresh_left, screen_refresh_right, hide=True)  # 加载的时候显示的组
screen_display_dict = {"load": group_load, "base": group_base, "test": group_test, "talk": group_talk, "connect6": group_connect6, "connect5": group_connect5}

def fix_show():
    # 隐藏与显示区域
    global now_display
    screen_display_dict[now_display].hide()
    screen_display_dict[aim_display].show()
    now_display = aim_display

def close_func(ppc):
    # 关闭当前的所有连接
    close_server_socket(button_net_link.message_dict) if job else close_client_socket(button_net_link.message_dict)
    print("关闭程序的最后一步")

def monitor_link(self: PyPixelController):
    # 每一分钟检测一次是否连接,以方便设置状态(设置在系统级的计时器中,是为了随时保持连接)
    global is_online
    if is_online:
        if button_net_link.message_dict["stop"]:
            # 执行断开操作
            is_online = False
            button_net_link.set_text_content("创<->建" if job else "连<->接")
            login_state_text_block.set_text_display("离线", color=Color_type.RED)

        if len(button_net_link.message_dict["message"]) == 0:
            return
        for message in button_net_link.message_dict["message"]:
            if message.message_type == "talk":
                net_game_message.add_text(f">{message.send_user}: {message.message_content}\n")
            if message.message_type == "game":
                net_game_message.add_text(f">{message.send_user}落子:{message.message_content}\n")
        button_net_link.message_dict["message"] = []


def main():
    ppc.close_func = close_func
    ppc.add_controller_timer_animation(CycleTimer(60), monitor_link)

    # 基础组
    button_base.set_click_up_func(click_and_swap_screem)

    # 测试组
    button_test.set_click_up_func(click_and_swap_screem)

    # 加载组
    refresh_text.set_timer_animation(CycleTimer(30), cycle_load)
    refresh_index.set_video_state("load")

    # 游戏六子棋组
    button_connect6.set_click_up_func(click_and_swap_screem)

    # 游戏五子棋组
    button_connect5.set_click_up_func(click_and_swap_screem)


    # 聊天室组
    select_job.set_click_down_func(chose_socket_connection)
    button_talk.set_click_up_func(click_and_swap_screem)
    button_net_link.set_click_down_func(start_socket_connection)
    message_input.reset_key_event(pygame.K_RETURN,None ,input_enter)
    send_button.set_click_down_func(send_message)

    # 组外块
    ppc.add_block(block_inform)

    # 修正初始化时的位置
    fix_show()
    # 添加组中的精灵进行管理
    ppc.add_groups(group_test,group_base,group_load,group_static,group_talk,group_connect6, group_connect5)
    # 启动引擎
    ppc.run()


if __name__ == '__main__':
    main()

